package com.hyh.net;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.concurrent.ConcurrentLinkedQueue;

import com.hyh.manager.ClientManager;
import com.hyh.model.Client;
import com.hyh.util.DateUtil;

public class NetPlatform {

	public static final int DataLength=2048;
	public static final int Port = 8888;
	private ConcurrentLinkedQueue<DatagramPacket> packetQueue = new ConcurrentLinkedQueue<>();
	private DatagramSocket socket;
	private OnRecvCallback onRecvCallback;
	
	public interface OnRecvCallback{
		void onCallback(DatagramPacket packet);
	} 
	
	public NetPlatform(OnRecvCallback onRecvCallback) {
		this.onRecvCallback = onRecvCallback;
		new ListenerThread().start();
		new HandlerThread().start();
		new InstrumentThread().start();
	}
	
	class InstrumentThread extends Thread{
		
		@Override
		public void run() {
			while(true){
				try {
					System.out.println("PacketQueue size is "+packetQueue.size()+" "+DateUtil.getDate());
					System.gc();
					Thread.sleep(10000);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		}
	}
	
	class ListenerThread extends Thread{
		
		@Override
		public void run() {
			try {
				socket = new DatagramSocket(Port);
				while(true){
					try {
						byte buf[] = new byte[DataLength];
						DatagramPacket packet = new DatagramPacket(buf, buf.length);
						socket.receive(packet);
						packetQueue.add(packet);
					} catch (IOException e) {
						e.printStackTrace();
					}
				}
			} catch (SocketException e) {
				e.printStackTrace();
			}
		}
	}
	
	class HandlerThread extends Thread{
		@Override
		public void run() {
			
			while(true){
				try {
					if(!packetQueue.isEmpty()){
						DatagramPacket packet = packetQueue.poll();
						if(onRecvCallback!=null&&packet!=null){
							onRecvCallback.onCallback(packet);
						}
					}else{
						Thread.sleep(1);
					}
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		}
	}
	
	public boolean send(DatagramPacket packet){
		
		try {
			socket.send(packet);
			return true;
		} catch (IOException e) {
			e.printStackTrace();
		}
		return false;
	}
	
	public boolean sendAll(DatagramPacket packet){
		List<Client> clientList =  ClientManager.getInstance().getAll();
		for(Client client:clientList){
			packet.setAddress(client.getAddr());
			packet.setPort(client.getPort());
			send(packet);
		}
		return true;
	}
}
